package blazingbubble.graphics.game;

import spark.exception.LoadingException;
import spark.math.Vector2;
import spark.graphics.ISpriteMap;
import spark.graphics.Sprite;
import spark.graphics.Texture;
import spark.graphics.SpriteMap;
import spark.identity.IIdentifiable;

import java.util.HashMap;

import moltencore.game.bubble.Type;

public class StaticSpriteMap implements ISpriteMap {
	public static final int BUBBLE_RED = 0;
	private static final int BUBBLE_RED_POSITION_X = 2;
	private static final int BUBBLE_RED_POSITION_Y = 0;
	public static final int BUBBLE_GREEN = 2;
	private static final int BUBBLE_GREEN_POSITION_X = 3;
	private static final int BUBBLE_GREEN_POSITION_Y = 0;
	public static final int BUBBLE_BLUE = 3;
	private static final int BUBBLE_BLUE_POSITION_X = 4;
	private static final int BUBBLE_BLUE_POSITION_Y = 0;
	public static final int BUBBLE_WHITE = 4;
	private static final int BUBBLE_WHITE_POSITION_X = 1;
	private static final int BUBBLE_WHITE_POSITION_Y = 0;
	public static final int BUBBLE_BLACK = 5;
	private static final int BUBBLE_BLACK_POSITION_X = 0;
	private static final int BUBBLE_BLACK_POSITION_Y = 0;
	public static final int BUBBLE_PURPLE = 6;
	private static final int BUBBLE_PURPLE_POSITION_X = 5;
	private static final int BUBBLE_PURPLE_POSITION_Y = 0;
	public static final int BUBBLE_ORANGE = 7;
	private static final int BUBBLE_ORANGE_POSITION_X = 6;
	private static final int BUBBLE_ORANGE_POSITION_Y = 0;
	public static final int BUBBLE_YELLOW = 8;
	private static final int BUBBLE_YELLOW_POSITION_X = 0;
	private static final int BUBBLE_YELLOW_POSITION_Y = 1;
	public static final int BUBBLE_BLAZING = 9;
	private static final int BUBBLE_BLAZING_POSITION_X = 1;
	private static final int BUBBLE_BLAZING_POSITION_Y = 1;
	public static final int BUBBLE_GHOST = 10;
	private static final int BUBBLE_GHOST_POSITION_X = 3;
	private static final int BUBBLE_GHOST_POSITION_Y = 1;
	public static final int BUBBLE_RAINBOW = 11;
	private static final int BUBBLE_RAINBOW_POSITION_X = 2;
	private static final int BUBBLE_RAINBOW_POSITION_Y = 1;
	public static final int BUBBLE_LION = 12;
	private static final int BUBBLE_LION_POSITION_X = 6;
	private static final int BUBBLE_LION_POSITION_Y = 1;
	public static final int BUBBLE_AWESOME = 13;
	private static final int BUBBLE_AWESOME_POSITION_X = 5;
	private static final int BUBBLE_AWESOME_POSITION_Y = 1;
	public static final int ARROW = 14;
	private static final int ARROW_POSITION_X = 4;
	private static final int ARROW_POSITION_Y = 1;
	public static final int BACKGROUND = 15;
	private static final int BACKGROUND_POSITION_X = 8;
	private static final int BACKGROUND_POSITION_Y = 1;
	private static final int BACKGROUND_WIDTH = 256;
	private static final int BACKGROUND_HEIGHT = 512;
	private static final int DEFAULT_GRAPHICS_DIMENSION = 512;
	private static final int BUBBLE_DIMENSION = 32;
	private static final int ARROW_DIMENSION_X = 32;
	private static final int ARROW_DIMENSION_Y = 32;

	private Texture texture;

	public StaticSpriteMap(Texture texture) {
		this.texture = texture;
	}

	public Sprite getBubble(Type type) throws LoadingException {
		switch(type) {
			case Black:
				return getBlackBubble();
			case Blazing:
				return getBlazingBubble();
			case Blue:
				return getBlueBubble();
			case Ghost:
				return getGhostBubble();
			case Green:
				return getGreenBubble();
			case Orange:
				return getOrangeBubble();
			case Violet:
				return getPurpleBubble();
			case Rainbow:
				return getRainbowBubble();
			case Red:
				return getRedBubble();
			case White:
				return getWhiteBubble();
			case Yellow:
				return getYellowBubble();
			default:
				throw new LoadingException("No such bubble " + type);
		}
	}

	public Sprite getFieldBackground() throws LoadingException {
		return getBackground();
	}

	public Sprite getCannon() throws LoadingException {
		return getArrow();
	}

	public Sprite getSprite(int spriteId) throws LoadingException {
		switch(spriteId) {
			case BUBBLE_AWESOME:
				return getAwesomeBubble();
			case BUBBLE_LION:
				return getLionBubble();
			case ARROW:
				return getArrow();
			default:
				throw new LoadingException("Invalid id" + spriteId);
		}
	}

	private Sprite getRedBubble() throws LoadingException {
		return new Sprite(
				texture, false,
				getPosition33x33Grid(BUBBLE_RED_POSITION_X, BUBBLE_RED_POSITION_Y),
				dimension(BUBBLE_DIMENSION, BUBBLE_DIMENSION));
	}

	private Sprite getGreenBubble() throws LoadingException {
		return new Sprite(
				texture, false,
				getPosition33x33Grid(BUBBLE_GREEN_POSITION_X, BUBBLE_GREEN_POSITION_Y),
				dimension(BUBBLE_DIMENSION, BUBBLE_DIMENSION));
	}

	private Sprite getBlueBubble() throws LoadingException {
		return new Sprite(
				texture, false,
				getPosition33x33Grid(BUBBLE_BLUE_POSITION_X, BUBBLE_BLUE_POSITION_Y),
				dimension(BUBBLE_DIMENSION, BUBBLE_DIMENSION));
	}

	private Sprite getWhiteBubble() throws LoadingException {
		return new Sprite(
				texture, false,
				getPosition33x33Grid(BUBBLE_WHITE_POSITION_X, BUBBLE_WHITE_POSITION_Y),
				dimension(BUBBLE_DIMENSION, BUBBLE_DIMENSION));
	}

	private Sprite getBlackBubble() throws LoadingException {
		return new Sprite(
				texture, false,
				getPosition33x33Grid(BUBBLE_BLACK_POSITION_X, BUBBLE_BLACK_POSITION_Y),
				dimension(BUBBLE_DIMENSION, BUBBLE_DIMENSION));
	}

	private Sprite getOrangeBubble() throws LoadingException {
		return new Sprite(
				texture, false,
				getPosition33x33Grid(BUBBLE_ORANGE_POSITION_X, BUBBLE_ORANGE_POSITION_Y),
				dimension(BUBBLE_DIMENSION, BUBBLE_DIMENSION));
	}

	private Sprite getPurpleBubble() throws LoadingException {
		return new Sprite(
				texture, false,
				getPosition33x33Grid(BUBBLE_PURPLE_POSITION_X, BUBBLE_PURPLE_POSITION_Y),
				dimension(BUBBLE_DIMENSION, BUBBLE_DIMENSION));
	}

	private Sprite getYellowBubble() throws LoadingException {
		return new Sprite(
				texture, false,
				getPosition33x33Grid(BUBBLE_YELLOW_POSITION_X, BUBBLE_YELLOW_POSITION_Y),
				dimension(BUBBLE_DIMENSION, BUBBLE_DIMENSION));
	}

	private Sprite getGhostBubble() throws LoadingException {
		return new Sprite(
				texture, false,
				getPosition33x33Grid(BUBBLE_GHOST_POSITION_X, BUBBLE_GHOST_POSITION_Y),
				dimension(BUBBLE_DIMENSION, BUBBLE_DIMENSION));
	}

	private Sprite getBlazingBubble() throws LoadingException {
		return new Sprite(
				texture, false,
				getPosition33x33Grid(BUBBLE_BLAZING_POSITION_X, BUBBLE_BLAZING_POSITION_Y),
				dimension(BUBBLE_DIMENSION, BUBBLE_DIMENSION));
	}

	private Sprite getRainbowBubble() throws LoadingException {
		return new Sprite(
				texture, false,
				getPosition33x33Grid(BUBBLE_RAINBOW_POSITION_X, BUBBLE_RAINBOW_POSITION_Y),
				dimension(BUBBLE_DIMENSION, BUBBLE_DIMENSION));
	}

	private Sprite getAwesomeBubble() throws LoadingException {
		return new Sprite(
				texture, false,
				getPosition33x33Grid(BUBBLE_AWESOME_POSITION_X, BUBBLE_AWESOME_POSITION_Y),
				dimension(BUBBLE_DIMENSION, BUBBLE_DIMENSION));
	}

	private Sprite getLionBubble() throws LoadingException {
		return new Sprite(
				texture, false,
				getPosition33x33Grid(BUBBLE_LION_POSITION_X, BUBBLE_LION_POSITION_Y),
				dimension(BUBBLE_DIMENSION, BUBBLE_DIMENSION));
	}

	private Sprite getArrow() throws LoadingException {
		return new Sprite(
				texture, false,
				getPosition33x33Grid(ARROW_POSITION_X, ARROW_POSITION_Y),
				dimension(ARROW_DIMENSION_X, ARROW_DIMENSION_Y));
	}

	private Sprite getBackground() throws LoadingException {
		return new Sprite(
				texture, true,
				getPosition256x256Grid(1, 0),
				dimension(BACKGROUND_WIDTH, BACKGROUND_HEIGHT));
	}

	private Vector2 getPosition33x33Grid(int x, int y) {
		float xPixels = ((float) x * (float) BUBBLE_DIMENSION) + (float) x + 1.0f;
		float yPixels = ((float) y * (float) BUBBLE_DIMENSION) + (float) y + 1.0f;
		return new Vector2(
				xPixels / (float) DEFAULT_GRAPHICS_DIMENSION,
				yPixels / (float) DEFAULT_GRAPHICS_DIMENSION);
	}

	private Vector2 getPosition256x256Grid(int x, int y) {
		float xPixels = (float) x * (float) 256;
		float yPixels = (float) y * (float) 256;
		return new Vector2(
				xPixels / (float) DEFAULT_GRAPHICS_DIMENSION,
				yPixels / (float) DEFAULT_GRAPHICS_DIMENSION);
	}

	private Vector2 dimension(int width, int height) {
		return new Vector2(
				(float) width / (float) DEFAULT_GRAPHICS_DIMENSION,
				(float) height / (float) DEFAULT_GRAPHICS_DIMENSION);
	}

	@Override
	public Sprite getSprite(String id) {
		try {
			if(id.toLowerCase().equals("cannon")) {
				return getArrow();
			}
			else if(id.toLowerCase().equals("red")) {
				return getBubble(Type.Red);
			}
			else if(id.toLowerCase().equals("green")) {
				return getBubble(Type.Green);
			}
			else if(id.toLowerCase().equals("blue")) {
				return getBubble(Type.Blue);
			}
			else if(id.toLowerCase().equals("orange")) {
				return getBubble(Type.Orange);
			}
			else if(id.toLowerCase().equals("yellow")) {
				return getBubble(Type.Yellow);
			}
			else if(id.toLowerCase().equals("violet")) {
				return getBubble(Type.Violet);
			}
			else if(id.toLowerCase().equals("black")) {
				return getBubble(Type.Black);
			}
			else if(id.toLowerCase().equals("white")) {
				return getBubble(Type.White);
			}
			else if(id.toLowerCase().equals("blazing")) {
				return getBubble(Type.Blazing);
			}
			else if(id.toLowerCase().equals("rainbow")) {
				return getBubble(Type.Rainbow);
			}
			else if(id.toLowerCase().equals("stone")) {
				return getBubble(Type.Ghost);
			}
		}
		catch(LoadingException e) {
			throw new SpriteMap.SpriteLoadFailedException(e);
		}
		throw new SpriteMap.SpriteLoadFailedException("NO such sprite " + id);
	}

	@Override
	public HashMap<String, Sprite> all() {
		HashMap<String, Sprite> all = new HashMap<String, Sprite>();
		try {
			all.put("cannon", getArrow());
			all.put("background", getFieldBackground());
			all.put("red", getBubble(Type.Red));
			all.put("green", getBubble(Type.Green));
			all.put("blue", getBubble(Type.Blue));
			all.put("yellow", getBubble(Type.Yellow));
			all.put("orange", getBubble(Type.Orange));
			all.put("violet", getBubble(Type.Violet));
			all.put("white", getBubble(Type.White));
			all.put("black", getBubble(Type.Black));
			all.put("rainbow", getBubble(Type.Rainbow));
			all.put("blazing", getBubble(Type.Blazing));
			all.put("stone", getBubble(Type.Ghost));
		}
		catch(LoadingException e) {
			throw new SpriteMap.SpriteLoadFailedException(e);
		}
		return all;
	}

	@Override
	public IIdentifiable getMapTextureId
			() {
		return null;
	}
}
